package com.mephi.oshs.presenter;

import com.mephi.oshs.Main;
import com.mephi.oshs.model.entry.IEntry;
import com.mephi.oshs.model.tree.OshsTree;
import com.mephi.oshs.view.api.IOshsView;
import com.mephi.oshs.view.api.IView;
import com.mephi.oshs.view.api.IViewManager;
import com.mephi.oshs.view.api.ViewId;
import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Text;
import org.eclipse.swt.widgets.Tree;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class PresenterManager {
    private static final Logger logger = LoggerFactory.getLogger(PresenterManager.class);

    private static PresenterManager singleton = null;

    private final Map<ViewId, IPresenter> presenters;
    private final IViewManager viewManager;

    private PresenterManager(final IViewManager viewManager) {
        this.viewManager = viewManager;
        this.presenters = new HashMap<ViewId, IPresenter>();
        logger.debug("PresenterManager(): created with " + viewManager);
    }

    public static synchronized PresenterManager getInstance() {
        return getInstance(Main.VIEW_MANAGER);
    }

    public static synchronized PresenterManager getInstance(final IViewManager viewManager) {
        return (singleton != null) ? singleton : (singleton = new PresenterManager(viewManager));
    }

    public void show() {
        final OshsTree<IEntry> oshsTree = OshsTree.getInstance();
        //this.observe(oshsTree);
        this.getOshsTreeView().getOshsTreeWidget().setTree(oshsTree);
    }

    public void bindView(final IView view) {
        if (view == null) {
            throw new NullPointerException("bindView(): View can't be null.");
        }

        IPresenter presenter;
        if (!this.presenters.containsKey(view.getViewID())) {
            switch (view.getViewID()) {
                case OSHS_VIEW:
                    presenter = new OshsPresenter();
                    break;

                case EXPLORE_VIEW:
                    presenter = new ExplorePresenter();
                    break;

                case SEARCH_VIEW:
                    presenter = new SearchPresenter();
                    break;
                default:
                    throw new RuntimeException("bindView(): Unknown view: " + view);
            }
            this.presenters.put(view.getViewID(), presenter);
        } else {
            presenter = this.presenters.get(view.getViewID());
        }

        presenter.bind();
    }

    public void unBindView(final IView view) {
        if (view == null) {
            throw new NullPointerException("bindView(): View can't be null.");
        }

        if (!this.presenters.containsKey(view.getViewID())) {
            throw new IllegalArgumentException("unBindView(): View wasn't bind before: " + view);
        }

        this.presenters.get(view.getViewID()).unbind();
    }

    public List<IPresenter> getAllPresenters() {
        return new ArrayList<IPresenter>(this.presenters.values());
    }

    public IPresenter getPresenterById(final ViewId viewId) {
        if (viewId == null) {
            throw new NullPointerException("bindView(): View can't be null.");
        }

        if (this.presenters.containsKey(viewId)) {
            return this.presenters.get(viewId);
        }
        throw new IllegalArgumentException("getPresenterById(): View id wasn't bind before: " + viewId);
    }

    public IViewManager getViewManager() {
        return viewManager;
    }

    private IOshsView getOshsTreeView() {
        return (IOshsView) getViewManager().getViewById(IOshsView.ID);
    }

    private void addActionListener(final Tree tree, final Text text) {
        tree.addListener(SWT.Selection, new Listener() {
            public void handleEvent(Event event) {
                if (event.detail == SWT.CHECK) {
                    text.setText(event.item + " was checked.");
                } else {
                    text.setText(event.item + " was selected");
                }
            }
        });
    }
}
